#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

void daemonize() {
  pid_t pid;
  int i, fd0, fd1, fd2;
  struct rlimit rl;

  getrlimit(RLIMIT_NOFILE, &rl);

  // 1. 设置 umask
  umask(0);

  // 2. 调用 fork，让父进程退出，保存子进程不是进程组组长
  if ((pid = fork()) < 0) {
    perror("fork");
    exit(-1);
  }
  else if (pid > 0) {
    // 让父进程退出
    exit(0);
  }

  // 3. 调用 setsid 创建新会话
  if (setsid() < 0) {
    perror("setsid");
    exit(-1);
  }

  // 4. 捕获 SIGHUP 信号。
  struct sigaction sa;
  sa.sa_handler = SIG_IGN;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  if (sigaction(SIGHUP, &sa, NULL) < 0) {
    perror("sigaction");
    exit(-1);
  }


  // 5. 更改工作目录
  if (chdir("/") < 0) {
    perror("chdir");
    exit(-1);
  }

  // 6. 关闭不用的描述符
  if (rl.rlim_max == RLIM_INFINITY) {
    rl.rlim_max = 1024;
  }
  for (i = 0; i < rl.rlim_max; ++i) {
    close(i);
  }

  // 7. 为守护进程打开 /dev/null，并让描述符 0、1、2 指向它
  fd0 = open("/dev/null", O_RDWR);
  fd1 = dup(0);
  fd2 = dup(0);
}

int  main() {

  printf("pid: %d, ppid: %d, sid: %d\n", getpid(), getppid(), getsid(getpid()));
  daemonize();

  int fd;
  char buf[256];

  while(1) {

    printf("pid: %d, ppid: %d, sid: %d\n", getpid(), getppid(), getsid(getpid()));
    fd = open("/home/allen/apue/relationship/daemon/test.log", O_WRONLY | O_APPEND | O_CREAT, 0664);
    if (fd > 0) {
      sprintf(buf, "pid: %d, ppid: %d, sid: %d\n", getpid(), getppid(), getsid(getpid()));
      write(fd, buf, strlen(buf));
    }

    sleep(3);
  }
  return 0;
}
